package com.kotlin.flong.coroutines1

import kotlinx.coroutines.*
import java.util.concurrent.Executors

/**
 * @Author:liangjl
 * @Date: 2020/7/8-19:20
 * @Eamil:jilongliang@sina.com
 * @Description: 协程与线程之间的关系
 *
 * 1、协程上下文与分发器(coroutine Context 与 Dispatcher)
 *
 * 2、协程总是会在某个上下文中执行，这个上下文实际上是由CoroutineContext类型的一个实例来表示的，该实例是由Kotlin标准库来定义的
 * 协程上下文本质是各种元素所构成的一个集合，其中，主要的元素包含协程Job，以及分发器
 *
 * 3、所谓分发器，其主要功能就是确定由哪个线程来执行我们所指定的协程代码
 *
 * 4、协程上下文包含了一个协程分发器(CoroutineDispatcher)，协程分发器确定了哪个写线程或者线程池来执行我们所指定的协程，协程分发器
 * 可以将协程的执行限制到一个具体指定的线程，也可以将协程的执行分发到一个线程池中，由线程池中的某个线程来执行我们所指定的协程 还可以不
 * 加任何限制地去执行我们所指定的协程代码(在这种情况下，我们所指定协程代码到底是由哪个线程或线程池来执行的是不确定的，它需要根据程序的实例
 * 执行情况能确定，这种方式的协程分发器一般开发过程中用得比较少的，它只用在一些极为特殊的情况下)
 *
 * 5、所有协程构建器(coroutine builder)如：launch和async都会接收一个可选的CoroutineContext参数，该参数可用显式指定新协程所运行
 * 的分发器以及其他上下文元素
 *-----------------------------------------------------
 * 程序分析：
 * 1、当通过launch来启动协程并且不指定协程分发器时，它会继承启动它的那个CoroutineScope的上下文与分发器，对于该示例来说，它会继承
 *  runBlocking的上下文，而runBlocking则是运行main线程当中
 *
 * 2、Dispatchers.Unconfined是一种很特殊的协程分发器，它在该示列中也运行在main线程中，但实际上，其运行机制与不指定协程分发器时完全不同的
 *   在日常开发过程中用得比较少
 *
 * 3、Dispatchers.Default是默认的分发器，当协程是通过GlobalScope来启动的时候，它会使用默认的分发器来启动协程，它会使用一个后台的共享线程
 *  池来运行我们的协程代码，因此launch(Dispatchers.Default)等价于GlobalScope.launch{ }
 *
 * 4、Executors.newSingleThreadExecutor().asCoroutineDispatcher()创建一个单线程的线程池，该线程池中的线程用来执行我们所指定的协程代码
 *   实际的开发中，使用专门的线程来执行代码代价非常高的，因此在协程代码执行完毕后，我们必须释放对应的资源，这里就需要使用close方法来关闭相应的协程
 *   分发器，也可以将协程分发器存储到一个顶层变量当中，以便在程序的其他地方进行复用。
 */

fun main() = runBlocking<Unit> {
    launch {
        println("no params ,thread ${Thread.currentThread().name} ")

    }
    launch(Dispatchers.Unconfined) {
        //把delay调用位置的线程的名称都不一样
        //delay(1000)
        println("Dispatchers Unconfined thread ${Thread.currentThread().name} ")
        //delay(1000)
    }

    launch(Dispatchers.Default) {
        println("Dispatchers Default thread ${Thread.currentThread().name} ")
    }

    //这行代码导致main方法一直不退出，因为此行代码并没由把线程关闭掉
    var thread = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
    launch(thread) {
        println("Executors newSingleThreadExecutor asCoroutineDispatcher thread ${Thread.currentThread().name} ")
        //关闭线程资源
        thread.close()
    }


    GlobalScope.launch() {
        println("GlobalScope launch thread ${Thread.currentThread().name} ")
    }


}





